home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Examples / Cards / UCards.p < prev   
Encoding:
Text File  |  1990-10-25  |  22.6 KB  |  619 lines  |  [TEXT/MPS ]

  1. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n+]}
  2. { UCards.p}
  3. { Copyright © 1986-1990 by Apple Computer, Inc.  All rights reserved. }
  4. {[f-]}
  5. {
  6.  
  7. This is an illustration of one way to implement disk-based documents in MacApp.
  8.  
  9. Some of the issues arising when using disk-based documents, and some of their
  10. possible solutions, are:
  11.  
  12.   (1)  When starting out with a new document, we need a disk-file behind it
  13.         from the outset (or at least from the first moment that the user
  14.         executes any command).    In non-disk-based apps, there is no need to
  15.         obtain a filename and a choice of which disk to write to until the user
  16.         requests a Save, but in the disk-based world we need somewhere to put
  17.         the data from the beginning.
  18.  
  19.        One solution, used by some apps, is to require the user to choose a
  20.         filename and a disk at the time NEW is requested or the app's own icon
  21.         is opened (e.g. Overvue).  This starts the user off in what can be a
  22.         rather confusing mode, however.
  23.  
  24.        Another solution is to use a standard filename, always allocating on the
  25.         boot volume or, perhaps on the default volume, for the new file (e.g.
  26.         disk-based MacWrite, which uses a file named 'NewFile').  This solution
  27.         may require that the app only support one document open at a time.
  28.         At application shut-down time, if not before, this file can be purged.
  29.  
  30.        A third, better, solution would be to choose an initial filename more
  31.         intelligently -- say make its name be a function of the application's
  32.         name and the date and time, perhaps, thus resolving name conflicts and
  33.         also giving the user more information if for some reason he should find
  34.         that file on his disk (such as after a power failure or application
  35.         crash).
  36.  
  37.  
  38.   (2)  When an existing file is opened and then the document is edited, if the
  39.         app wishes to support 'Revert' then it must preserve information both
  40.         about the previously-saved state and about the changes made.  This adds
  41.         complexity to the design.
  42.  
  43.        One solution is to retain two copies of the document file, one of which
  44.         has the most recently saved version, and the other the current
  45.         working-version.    Thus, one always has something to revert to.  When
  46.         reopening an old document, the app starts out by making a complete,
  47.         exact, copy of it in a new file (attaching the original filename to one
  48.         or the other and a temporary filename to whichever one doesn't retain
  49.         the original filename).  All edits are then made on the copy.  Each
  50.         time there is a Save, the current working version becomes the 'saved'
  51.         version, and a copy of it becomes the current working version (or
  52.         something equivalent to that).
  53.  
  54.        This solution has the problem that during editing of a document, twice
  55.         as much disk is consumed as necessary. But it leads to cleanliness of
  56.         design.
  57.  
  58.        Another solution is to retain in a single disk file all the information
  59.         about the most-recently saved version AND all the changes since then.
  60.         This requires a more complex file format.
  61.  
  62.        A third solution is to use the latest Save-file as a read-only data base,
  63.         with all changes posted to a second, read-write 'Changes' file. In this
  64.         scheme, each "Save" is carried out by merging the edits logged in the
  65.         Changes file with the data in the latest Save file, thus producing a
  66.         new Save-file, at which time the Changes file is reset to empty.  This
  67.         solution is clean and comprehensive, but requires quite a bit more code
  68.         and design, since the application must understand two different file
  69.         formats, must be able to merge save-data and changes-data dynamically
  70.         so that the appearance on the screen is right, etc.
  71.  
  72.        A fourth solution is to abandon the 'Revert to Previous Version' feature.
  73.         In this case, the actual Save-file can be opened for read-write, left
  74.         open throughout the time the document is open, and it can be updated in
  75.         place.
  76.  
  77.  
  78.    In this simple example, easier alternatives were chosen at most junctures.
  79.    Thus:
  80.  
  81.     --    An open document has two disk files, which we will call the Working File
  82.             and the Saved File; but an open document that has never been saved
  83.             does not have a Saved File yet.
  84.     --    The 'Saved File' has the most recently saved version, and resides in a
  85.             file whose name is the same as the one the user thinks of.
  86.     --    The 'Working File' is a file with a generated name on the default volume
  87.             (if the default volume can't be written to, or doesn't have enough
  88.             space to hold this file, an error is issued, and editing cannot
  89.             proceed -- this is the same as in MacWrite).
  90.     --    Each time there is a Save, the following process is followed:  A new
  91.             saved file is created by copying over everything from the Working
  92.             file and existing Saved file.
  93.     --    Revert is implemented by clearing the Working File.
  94.     --    For "Save As", the old Saved File is abandoned in whatever state it was
  95.         in, and a new Saved File is created as for Save.
  96.  
  97.  
  98.    C A C H I N G:
  99.  
  100.         In a disk-based document, some of the data are available in memory and
  101.         others must be read from disk.    To avoid having to go to disk too often,
  102.         it is expedient to implement a caching scheme, whereby the last n data
  103.         objects (paragraphs, file records, notecards, what have you) are kept
  104.         in memory.
  105.  
  106.         An easy caching scheme is offered here.
  107.  
  108.         The model followed is that ALL cards belonging to a document are
  109.         representing by OBJECTS in memory (a List of elements of type TCard).
  110.         The information stored in the TCard object itself is minimal.  The full
  111.         information about any Card is stored on Disk, and is brought into the
  112.         cache in memory only when required (typically when it is displayed as
  113.         the current card).
  114.  
  115.         The Cache is represented by another List, whose elements are also of
  116.         type TCard.  It is maintained on a First-in First-out basis, so that
  117.         the most recently accessed n cards are in the cache.
  118.  
  119.         Typically, a TCard item will have a handle to its lengthier data, which
  120.         will be NIL (or perhaps some negative value, to store retrieval
  121.         information or something else useful) when the Card is not in the cache,
  122.         but will be a true handle to data when it is in the cache.
  123.  
  124.  }
  125. {[f+]}
  126.  
  127. UNIT UCards;
  128.  
  129.     INTERFACE
  130.  
  131.         USES
  132.  
  133.             { • MacApp }
  134.             UMacApp,
  135.  
  136.             { • Building Blocks }
  137.             UPrinting, UTEView,
  138.  
  139.             { • Implementation use }
  140.             Packages, ToolUtils;
  141.  
  142.         CONST
  143.  
  144.             cNextCard            = 1000;                 { Next Card command }
  145.             cPrevCard            = 1001;                 { Previous Card command }
  146.             cFirstCard            = 1002;                 { First Card command }
  147.             cLastCard            = 1003;                 { Last Card command }
  148.             cNewCard            = 1010;                 { New Card command }
  149.             cDeleteCard         = 1011;                 { Delete Card command }
  150.             kSignature            = 'SS10';                { Application signature }
  151.             kFileType            = 'SF10';                { File-type code used for document files
  152.                                                           created by this application }
  153.  
  154.             kWindowRsrcID        = 1000;                 { Id of the window view template }
  155.             kCardViewRsrcID     = 1001;                 { Id of the card view template }
  156.  
  157.             kWorkType            = 'SW10';                { File type for the work file }
  158.  
  159.         TYPE
  160.  
  161.             CardDocData         =                        { This is the data stored at the beginning
  162.                                                          of the disk file }
  163.                 RECORD
  164.                 theCardCount:        INTEGER;            { number of cards in the document }
  165.                 theShownCard:        INTEGER;            { Card currently being shown, or -1 }
  166.                 { ??? add window-state info, etc., here }
  167.                 END;
  168.  
  169.             TCardsApplication    = OBJECT (TApplication)
  170.  
  171.                 PROCEDURE TCardsApplication.ICardsApplication;
  172.                 { Initialize the application }
  173.  
  174.                 FUNCTION TCardsApplication.DoMakeDocument(itsCmdNumber: CmdNumber): TDocument;
  175.                                                           OVERRIDE;
  176.                 { Launches a TCardsDocument; called when application's icon is opened,
  177.                   and when New or Open is requested by the user }
  178.  
  179.                 PROCEDURE TCardsApplication.DoShowAboutApp; OVERRIDE;
  180.                 { Overridden in order to give a current-status report when "About <appName>"
  181.                   is selected from the apple menu }
  182.  
  183.                 END;
  184.  
  185.             {$IFC qHasForward}
  186.             TCardView             = OBJECT;    FORWARD;
  187.             TEmptyView            = OBJECT;    FORWARD;
  188.             TCardCache            = OBJECT;    FORWARD;
  189.             TCard                = OBJECT;    FORWARD;
  190.             {$EndC}
  191.  
  192.             TCardDocument        = OBJECT (TDocument)
  193.  
  194.                 fCardView:            TCardView;            { The view that shows the cards }
  195.                 fEmptyView:         TEmptyView;         { The view that says there are no cards }
  196.                 fCurrView:            TView;                { Which view are we looking at? }
  197.  
  198.                 fCards:             TList;                { a list containing a TCard object for each
  199.                                                           card in the data base; it serves as a
  200.                                                           dictionary for the data base }
  201.  
  202.                 fCache:             TCardCache;         { a list of cards cached in memory; all
  203.                                                           others have their data available only by
  204.                                                           going to disk }
  205.  
  206.                 fCardDocData:        CardDocData;        { Info about the document's contents }
  207.  
  208.                 fReopening:         BOOLEAN;            { Used when we restore window state (not
  209.                                                           done now) }
  210.  
  211.                 fWorkFileName:        Str255;             { Name of the current work file }
  212.                 fWorkVRefNum:        INTEGER;            { Volume refNum of the current work file }
  213.                 fWorkRefNum:        INTEGER;            { Refnum of the current work file }
  214.  
  215.                 fWorkNext:            LONGINT;            { File-location for next new card to be
  216.                                                           added to the work file }
  217.  
  218.                 fFirstWritten:        LONGINT;            { File-location of first card written during
  219.                                                           last DoWrite }
  220.  
  221.                         { Initialization and termination }
  222.  
  223.                 PROCEDURE TCardDocument.ICardDocument;
  224.                 { Initialize the document }
  225.  
  226.                 PROCEDURE TCardDocument.Free; OVERRIDE;
  227.                 { Free the document }
  228.  
  229.                         { TDocument methods for opening and closing }
  230.  
  231.                 PROCEDURE TCardDocument.FreeData; OVERRIDE;
  232.                 { Deletes the work file and in-memory structures }
  233.  
  234.                 PROCEDURE TCardDocument.DoInitialState; OVERRIDE;
  235.                 { Set up empty document }
  236.  
  237.                 PROCEDURE TCardDocument.DoMakeViews(forPrinting: BOOLEAN); OVERRIDE;
  238.                 { Launches the views which are seen in the document's window }
  239.  
  240.                 PROCEDURE TCardDocument.ShowReverted; OVERRIDE;
  241.                 { Set the views properly when reverting }
  242.  
  243.                 PROCEDURE TCardDocument.SwapViews(fromView, toView: TView);
  244.                 { Swap current view }
  245.  
  246.                         { Overrides of TDocument methods for Filing }
  247.  
  248.                 PROCEDURE TCardDocument.DoNeedDiskSpace(VAR dataForkBytes,
  249.                                                         rsrcForkBytes: LONGINT); OVERRIDE;
  250.                 { Tells how many bytes of disk space will be required to store the
  251.                   data for the document in a file on disk }
  252.  
  253.                 PROCEDURE TCardDocument.DoRead(aRefNum: INTEGER; rsrcExists,
  254.                                                forPrinting: BOOLEAN); OVERRIDE;
  255.                 { Actually reads in the data from the disk, when a document is
  256.                   Opened or Reverted }
  257.  
  258.                 PROCEDURE TCardDocument.DoWrite(aRefNum: INTEGER; makingCopy: BOOLEAN); OVERRIDE;
  259.                 { Actually writes the data to the disk, when a document is Saved }
  260.  
  261.                         { Work-file management }
  262.  
  263.                 PROCEDURE TCardDocument.ConstructCardIndex(aRefNum: INTEGER);
  264.                 { Build the in-memory index to the card document }
  265.  
  266.                 PROCEDURE TCardDocument.CreateWorkFile;
  267.                 { Creates the Work file }
  268.  
  269.                 PROCEDURE TCardDocument.EmptyWorkFile;
  270.                 { Resets the work file to be empty }
  271.  
  272.                 PROCEDURE TCardDocument.PurgeWorkFile;
  273.                 { Purges the Work file }
  274.  
  275.                         { Menu management }
  276.  
  277.                 PROCEDURE TCardDocument.DoSetupMenus; OVERRIDE;
  278.                 { Enable menu commands }
  279.  
  280.                 FUNCTION TCardDocument.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; OVERRIDE;
  281.                 { Handle menu commands }
  282.  
  283.                         { Card management }
  284.  
  285.                 FUNCTION TCardDocument.AddCard: INTEGER;
  286.                 { Add a card to the document's data set }
  287.  
  288.                 PROCEDURE TCardDocument.DeleteCard(aCard: TCard);
  289.                 { Called when a card is to be deleted from the file }
  290.  
  291.                 PROCEDURE TCardDocument.CacheCard(aCard: TCard);
  292.                 { If the card is not currently in the cache, read it from disk,
  293.                   first making space in the cache if neceessary; if it already
  294.                   IS in the cache, move it to the front of the cache, so that it
  295.                   will be the last to be pushed out }
  296.  
  297.                 PROCEDURE TCardDocument.ReadCardFromDisk(aCard: TCard);
  298.                 { Reads the card into the work file }
  299.  
  300.                 FUNCTION TCardDocument.FirstCard: INTEGER;
  301.                 { Return the first non-deleted card in the file }
  302.  
  303.                 FUNCTION TCardDocument.LastCard: INTEGER;
  304.                 { Return the last non-deleted card in the file }
  305.  
  306.                 FUNCTION TCardDocument.NextCard(theCard: INTEGER): INTEGER;
  307.                 { Return the next non-deleted card after the given card }
  308.  
  309.                 FUNCTION TCardDocument.PrevCard(theCard: INTEGER): INTEGER;
  310.                 { Return the previous non-delete card before the given card }
  311.  
  312.                 PROCEDURE TCardDocument.PurgeCards;
  313.                 { Delete all card objects associated with the document }
  314.  
  315.                 PROCEDURE TCardDocument.SavedOn(VAR fileName: Str255; volRefNum: INTEGER); OVERRIDE;
  316.                 { Note that we are using a new disk file }
  317.  
  318.                 PROCEDURE TCardDocument.WriteCardToDisk(aCard: TCard);
  319.                 { Writes the card out to the work file }
  320.  
  321.                         { Inspecting }
  322.                 PROCEDURE TCardDocument.Fields(PROCEDURE
  323.                                                DoToField(fieldName: Str255; fieldAddr: Ptr;
  324.                                                          fieldType: INTEGER)); OVERRIDE;
  325.  
  326.                 END;
  327.  
  328.             {$IFC qHasForward}
  329.             TCardEditCommand    = OBJECT;    FORWARD;
  330.             {$EndC}
  331.  
  332.             TCardView            = OBJECT (TTEView)
  333.             { TCardView is the view used to show a card in the card window }
  334.  
  335.                 fCardDocument:        TCardDocument;        { Card document shown in view }
  336.                 { ??? In retrospect, the next two fields really should belong to
  337.                   TCardDocument, as they represent document state and we have to do
  338.                   a lot of gymnastics now to keep TCardView in synch with TCardDocument. }
  339.                 fCurrCard:            TCard;                { The currently shown card }
  340.                 fCurrNumber:        INTEGER;            { Index of card being shown }
  341.                 fCardEditCommand:    TCardEditCommand;    { Current editing command, if any }
  342.  
  343.                         { Creation/Destruction methods }
  344.  
  345.                 PROCEDURE TCardView.IRes(itsDocument: TDocument; itsSuperView: TView;
  346.                                          VAR itsParams: Ptr); OVERRIDE;
  347.                 { Create the view from a resource template}
  348.  
  349.                 PROCEDURE TCardView.Free; OVERRIDE;
  350.                 { Free our data before disposing }
  351.  
  352.                         { View business }
  353.  
  354.                 PROCEDURE TCardView.InstallText(newText: Handle);
  355.                 { Change the contents of this view to the specified text }
  356.  
  357.                 PROCEDURE TCardView.ShowReverted; OVERRIDE;
  358.                 { Adjust the view after a revert }
  359.  
  360.                         { Card handling }
  361.  
  362.                 PROCEDURE TCardView.InstallCard(theCard: INTEGER);
  363.                 { Make the specified card the current card }
  364.  
  365.                 PROCEDURE TCardView.UpdateCard(theCard: TCard);
  366.                 { theCard is no longer the current card; update its text if necessary }
  367.  
  368.                         { Commands and Menus }
  369.  
  370.                 FUNCTION  TCardView.DoKeyCommand(ch: Char; aKeyCode: INTEGER;
  371.                                                 VAR info: EventInfo): TCommand; OVERRIDE;
  372.                 { Capture command coming back from TEView.DoKeyCommand }
  373.  
  374.                 FUNCTION  TCardView.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; OVERRIDE;
  375.                 { Handle menu commands, including those for TEView }
  376.  
  377.                 PROCEDURE TCardView.DoSetupMenus; OVERRIDE;
  378.                 { Enable the appropriate menu choices }
  379.  
  380.                         { Inspecting }
  381.                 PROCEDURE TCardView.Fields(PROCEDURE
  382.                                            DoToField(fieldName: Str255; fieldAddr: Ptr;
  383.                                                      fieldType: INTEGER)); OVERRIDE;
  384.  
  385.                 END;
  386.  
  387.  
  388.             TEmptyView            = OBJECT (TView)
  389.             { TEmptyView is used to show a message when there are no cards in the
  390.               database.  It could have been part of TCardView, but swapping views is
  391.               easier than overriding all the methods of TTEView which would have to
  392.               do nothing if there were no card showing. }
  393.  
  394.                 PROCEDURE TEmptyView.Resize(width, height: VCoordinate;
  395.                                            invalidate: BOOLEAN); OVERRIDE;
  396.                 { Force a redraw on resize since the text is filled to the box }
  397.                 PROCEDURE TEmptyView.Draw(area: Rect); OVERRIDE;
  398.                 { Draw the view saying there are no cards }
  399.  
  400.                 END;
  401.  
  402.             TCacheableObject    = OBJECT (TObject)
  403.                 fGeneration:        INTEGER;            { How long I've been lying around in memory
  404.                                                          }
  405.                 fLocked:            BOOLEAN;            { Object cannot be purged from the cache }
  406.  
  407.                 PROCEDURE TCacheableObject.ICacheableObject;
  408.                 { Initialize the cacheableobject }
  409.  
  410.                 PROCEDURE TCacheableObject.Fields(PROCEDURE
  411.                                                   DoToField(fieldName: Str255; fieldAddr: Ptr;
  412.                                                             fieldType: INTEGER)); OVERRIDE;
  413.  
  414.                 END;
  415.  
  416.             TCard                = OBJECT (TCacheableObject)
  417.             { There is one TCard object for every card in the database. }
  418.  
  419.                 fData:                Handle;             { Handle to the data on the card; if NIL,
  420.                                                           card is not in memory }
  421.                 fDataSize:            INTEGER;            { Number of bytes of data on the card (same
  422.                                                           as GetHandleSize(fData) when fData is in
  423.                                                           memory) }
  424.                 fDirty:             BOOLEAN;            { Whether the data on the card has been
  425.                                                           changed since it was last read in from
  426.                                                           disk }
  427.                 fChanged:            BOOLEAN;            { Whether the card currently resides in work
  428.                                                           file }
  429.                 fDeleted:            BOOLEAN;            { Whether the card has been deleted from the
  430.                                                           file }
  431.  
  432.                 fLocInFile:         LONGINT;            { Location of the card's data in the
  433.                                                           database file }
  434.  
  435.                 fCardDocument:        TCardDocument;        { The document I belong to }
  436.  
  437.                         { Initialization, destruction }
  438.  
  439.                 PROCEDURE TCard.ICard(itsFileLocation: LONGINT; itsDocument: TCardDocument);
  440.                 { Initialize the card }
  441.  
  442.                 PROCEDURE TCard.Free; OVERRIDE;
  443.                 { Hose the card }
  444.  
  445.                         { Modification }
  446.  
  447.                 PROCEDURE TCard.Changed(itsFileLocation: LONGINT);
  448.                 { This card should be sent to the work file }
  449.  
  450.                 PROCEDURE TCard.NewText(aHandle: Handle);
  451.                 { The card has some new text }
  452.  
  453.                         { Filing }
  454.  
  455.                 PROCEDURE TCard.NewHome(itsFileLocation: LONGINT);
  456.                 { Note that the card has a new place in the document file }
  457.  
  458.                 PROCEDURE TCard.ReadFrom(aRefNum: INTEGER);
  459.                 { Read the card's data from disk }
  460.  
  461.                 PROCEDURE TCard.WriteTo(aRefNum: INTEGER);
  462.                 { Write the card's data to disk }
  463.  
  464.                 PROCEDURE TCard.WriteCopy(aRefNum: INTEGER);
  465.                 { Write the card's data to some file }
  466.  
  467.                         { Inspecting }
  468.                 PROCEDURE TCard.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  469.                                                            fieldType: INTEGER)); OVERRIDE;
  470.  
  471.                 END;
  472.  
  473.             TCardCache            = OBJECT (TList)
  474.             { Again a card cache really is too specific of an object because it has knowledge
  475.                 from the programmer about what types of objects it is going to contain (namely cards).
  476.                 If we wanted to generalize, functions such as cachecard, cardisincache, etc. would
  477.                 take an additional argument which would be a predicate function (that is, a function
  478.                 that returns true or false) to some question.  For example, CardIsInCache might
  479.                 become:
  480.                 TCache.IsInCache(PROCEDURE TEST(anObject: TObject); anObject: TObject); }
  481.  
  482.                 fMaxSize:            INTEGER;            { How large can I grow }
  483.                 fGrowthRate:        INTEGER;            { How fast to grow after I hit my limit and
  484.                                                           no cards are purgable }
  485.                 fGeneration:        INTEGER;            { Generation of last object in the cache }
  486.  
  487.                 PROCEDURE TCardCache.ICardCache(size, growth: INTEGER);
  488.  
  489.                 PROCEDURE TCardCache.CacheCard(aCardDocument: TCardDocument; aCard: TCard);
  490.  
  491.                 FUNCTION  TCardCache.CardIsInCache(aCard: TCard): BOOLEAN;
  492.  
  493.                 PROCEDURE TCardCache.Delete(item: TObject); OVERRIDE;
  494.  
  495.                 PROCEDURE TCardCache.FreeDocCards(aCardDocument: TCardDocument);
  496.  
  497.                 PROCEDURE TCardCache.Insert(item: TObject); OVERRIDE;
  498.  
  499.                 PROCEDURE TCardCache.Grow;
  500.  
  501.                 FUNCTION  TCardCache.PurgeableCard(aCardDocument: TCardDocument): TCard;
  502.  
  503.                 PROCEDURE TCardCache.Touch(aCard: TCard);
  504.  
  505.                 PROCEDURE TCardCache.Fields(PROCEDURE
  506.                                             DoToField(fieldName: Str255; fieldAddr: Ptr;
  507.                                                       fieldType: INTEGER)); OVERRIDE;
  508.  
  509.                 END;
  510.  
  511.             TCardEditCommand    = OBJECT (TCommand)
  512.             { TCardEditCommand objects are used to "encapsulate" TCommand when a
  513.               card is being edited (either via the Edit menu or typing).  A cleaner
  514.               mechanism is provided by the TTEView methods DoMakeEditCommand and
  515.               DoMakeTypingCommand, which can be overridden to return a descendant
  516.               command object instead.  But in this case, TCardEditCommand doesn't
  517.               care whether it's dealing with a TTETypingCommand or an Edit menu
  518.               command, so rather than declare one descendant of TTECommand and one
  519.               descendant of TTETypingCommand, which both do the same thing, we use
  520.               the TTECommand as a subsidiary object to our own command. }
  521.  
  522.                 fEncapsulatedCommand:         TCommand;     { encapsulated TCommand }
  523.                 fCardView:            TCardView;            { associated CardView }
  524.                 fCardNumber:        INTEGER;            { number of card being edited }
  525.                 fCard:                TCard;                { card itself }
  526.                 fReserve:            Handle;                { Use to "reserve" memory--it is used to
  527.                                                           ensure there is enough memory to copy
  528.                                                           the TEView's text to the card when
  529.                                                           Commit calls UpdateCard. }
  530.  
  531.                 PROCEDURE TCardEditCommand.ICardEditCommand(itsCmdNumber: CmdNumber;
  532.                                                             itsView: TCardView;
  533.                                                             itsEncapsulatedCommand: TCommand);
  534.  
  535.                 PROCEDURE TCardEditCommand.Free; OVERRIDE;
  536.                 { Clean up }
  537.  
  538.                 PROCEDURE TCardEditCommand.DoIt; OVERRIDE;
  539.                 { Perform the edit of the card }
  540.  
  541.                 PROCEDURE TCardEditCommand.UndoIt; OVERRIDE;
  542.                 { Undo the edit to the card }
  543.  
  544.                 PROCEDURE TCardEditCommand.RedoIt; OVERRIDE;
  545.                 { Redo the edit to the card }
  546.  
  547.                 PROCEDURE TCardEditCommand.Commit; OVERRIDE;
  548.                 { Commit the edit to the card }
  549.  
  550.                 PROCEDURE TCardEditCommand.Fields(PROCEDURE
  551.                                                   DoToField(fieldName: Str255; fieldAddr: Ptr;
  552.                                                             fieldType: INTEGER)); OVERRIDE;
  553.  
  554.                 END;
  555.  
  556.             TNewCardCommand     = OBJECT (TCommand)
  557.             { This command is used to create a new card. }
  558.  
  559.                 fCardDocument:        TCardDocument;        { associated card document }
  560.                 fCardNumber:        INTEGER;            { number of card being added }
  561.                 fCard:                TCard;                { card itself }
  562.                 fSavedSelection:    INTEGER;            { Saved number of currently selected card }
  563.  
  564.                 PROCEDURE TNewCardCommand.INewCardCommand(itsCmdNumber: CmdNumber;
  565.                                                           itsCardDocument: TCardDocument);
  566.  
  567.                 PROCEDURE TNewCardCommand.DoIt; OVERRIDE;
  568.                 { Perform the addition of the card }
  569.  
  570.                 PROCEDURE TNewCardCommand.UndoIt; OVERRIDE;
  571.                 { Undo the addition of the card }
  572.  
  573.                 PROCEDURE TNewCardCommand.RedoIt; OVERRIDE;
  574.                 { Redo the addition of the card }
  575.  
  576.                 PROCEDURE TNewCardCommand.Commit; OVERRIDE;
  577.                 { Commit the addition of the card }
  578.  
  579.                 PROCEDURE TNewCardCommand.Fields(PROCEDURE
  580.                                                  DoToField(fieldName: Str255; fieldAddr: Ptr;
  581.                                                            fieldType: INTEGER)); OVERRIDE;
  582.  
  583.                 END;
  584.  
  585.             TDeleteCardCommand    = OBJECT (TCommand)
  586.             { This command is used to delete an existing card. }
  587.  
  588.                 fCardDocument:        TCardDocument;        { associated card document }
  589.                 fCardNumber:        INTEGER;            { number of card being added }
  590.                 fCard:                TCard;                { card itself }
  591.  
  592.                 PROCEDURE TDeleteCardCommand.IDeleteCardCommand(itsCmdNumber: CmdNumber;
  593.                                                                 itsCardDocument: TCardDocument;
  594.                                                                 itsCard: TCard; itsNumber: INTEGER);
  595.  
  596.                 PROCEDURE TDeleteCardCommand.DoIt; OVERRIDE;
  597.                 { Perform the deletion of the card }
  598.  
  599.                 PROCEDURE TDeleteCardCommand.UndoIt; OVERRIDE;
  600.                 { Undo the deletion of the card }
  601.  
  602.                 PROCEDURE TDeleteCardCommand.RedoIt; OVERRIDE;
  603.                 { Redo the deletion of the card }
  604.  
  605.                 PROCEDURE TDeleteCardCommand.Commit; OVERRIDE;
  606.                 { Commit the deletion of the card }
  607.  
  608.                 PROCEDURE TDeleteCardCommand.Fields(PROCEDURE
  609.                                                     DoToField(fieldName: Str255; fieldAddr: Ptr;
  610.                                                               fieldType: INTEGER)); OVERRIDE;
  611.  
  612.                 END;
  613.  
  614.     IMPLEMENTATION
  615.  
  616.         {$I UCards.inc1.p}
  617.  
  618. END.
  619.